 
import { ABaseDecision } from "GameLoop/DecisionMaking/BaseDecision";
import { MainStrategy } from "GameLoop/WorldState/EntityManager/CreateStrategy/MainStrategy";
import { getRoleConfig } from "utils/constants/bodyconstant";
import { priority } from "utils/constants/definetypes";
import { BodyEfficiency } from "utils/creep/bodyEfficiency";
import { TaskHelper } from "utils/task/TaskHelper";

/**
 * 修理任务决策
 */
export class RepairDecision< T extends "creep"|"tower"="creep"|"tower"> extends ABaseDecision<T>
{
   
    public isExpired(event: NormalEvent, region: string): boolean 
    {
        let taskid =  `${event.room}_creep_repair`;
        const room = Game.rooms[event.region];
        if(room.controller?.level ==1)
        {
            return false;
        }
        let task = room.findTaskById(taskid,"creep");
        if(task)
        {
            return false;
        }
        taskid =  `${event.room}_tower_repair`;
 
        task = room.getTaskById(taskid,["tower","room"]);
        if(task)
        {
            return false;
        }
        return true;
    }
    public makeTask(event: NormalEvent, region: string): IDecisionCode<T>|false
    {
        
        // global.Log.Info(`维修任务`);
        const lordroom = Game.rooms[event.region] as Required<Room>;
        const thisroom = Game.rooms[event.room];
        const structcache = this.WorldGetter.Station.PollStructure(event.room);

        if(!structcache)
        {
            return false;
        }
        const repairgoal = this.getRepairGoal(thisroom);
        if(!repairgoal || repairgoal.goalArray.length==0)
        {
            return false;
        }
        if(thisroom.towers().length>0 && event.region == event.room)
        {
            const repairTask:IRoomTaskData<"towerRepair"> = 
            {
                type: "towerRepair",
                arg: {
                    room: thisroom.name,
                    targets: repairgoal.goal
                },
                
            }
            const code:IDecisionCode<"tower">={
                region:event.region,
                isunique:false,
                task:[{
                    id:`${event.room}_tower_repair`,
                    ttl:5000,
                    priority:priority.D,
                    type:"tower",
                    data:repairTask,
                    shard:0,
                }  ],
            }
            return code as any
        }
        else
        {
            if(thisroom.controller?.owner)
            {
                return false;
            }
            // Memory.Debug[`${Game.time}-发布爬虫维修任务 towers:${thisroom.towers().length}`] = event;
            // 这里的计算可以再优化！
            

            let repair_sum =  _.sum(repairgoal.goalArray ,e=>e[1]-Game.getObjectById(e[0])!.hits);
            const body = getRoleConfig("worker",lordroom.controller.level);
            const expire_work_count =  BodyEfficiency.calCreepCountByProgress(repair_sum,body.body,"repair");
            const worker_count = Math.min( expire_work_count,10);
            const repairTask:ICreepTaskData<"repair"> = 
            {
                type:"repair",
                arg:{
                    room:thisroom.name,
                    targets:repairgoal.goalArray
                },
                room:thisroom.name,
                creeps:[],
                body:{},
                income:-1,
                cost:TaskHelper.getTaskPathCost(event.region,event.room),
                required:[
                    [['worker'],Math.max(1,worker_count),Math.max(1,worker_count)]
                ]
            }
             // 根据升级共数量。计算运输工数量
            const code:IDecisionCode<T>={
                region:event.region,
                isunique:false,
                task:[{
                    id:`${event.room}_creep_repair`,
                    ttl:5000,
                    priority:priority.D,
                    type:"creep",
                    data:repairTask,
                    shard:Math.max(1,worker_count),
                } as any],
            }
            return code
        }
        
        // return false;
    }
    

    private getRepairGoal(room:Room)
    {
        const structcache = this.WorldGetter.Station.PollStructure(room.name);

        if(!structcache)
        {
            return false;
        }
        let repair_sum=0;
        const getRepairGoals = (types:StructureConstant[],radio:number=0.9)=>
        {
            const repairgoal:Record<string,number>={};
            const goalArray:[Id<Structure>,number][]=[];
            let shouldrepair = false;
            
            for(const type of types)
            {
                if(type == STRUCTURE_ROAD && room.lordRoom().controller.level<=3)
                {
                    // 3级前不修路
                    continue;
                }
                else if(type == STRUCTURE_CONTAINER && room.lordRoom().controller.level<2)
                {
                    // 不到2级不修container
                    continue;
                }
                const structures = structcache.getStructure(type);
                if(structures)
                {
                    
                    for(const e of structures)
                    {
                        const obj = Game.getObjectById(e.id);
                        if(obj  )
                        {
                            if(obj.hits<obj.hitsMax*radio)
                            {
                                shouldrepair = true;
                            }
                            repairgoal[obj.id] = obj.hitsMax;
                            repair_sum+=obj.hitsMax-obj.hits;
                            goalArray.push([obj.id,obj.hitsMax]);
                        }
                    }
                    
                }
            }
            
            return {isrepair:shouldrepair, goal:repairgoal,goalArray:goalArray}
        }
        let repairgoal:{structuures:StructureConstant[],interval:number,radio:number}[]=[];
       
        if(room.getType() == 1)
        {
            // 主房
            repairgoal = [
                {
                    structuures:[STRUCTURE_CONTAINER,STRUCTURE_ROAD],
                    interval:200,
                    radio:0.7
                }
            ]
        }
        else
        {
            // 外矿房
            repairgoal = [
                {
                    structuures:[STRUCTURE_ROAD],
                    interval:200,
                    radio:0.6
                }
            ]
        }
        for(const f of repairgoal)
        {
            if(!room.canExecute(f.interval))
            {
                continue
            }
            const repairgoal = getRepairGoals(f.structuures,f.radio);
     
            if(repairgoal &&  repairgoal.isrepair)
            {
                return repairgoal;
            }
        }
        return false;
    }
}